package net.mayee.alice.web.controller.admin.profile;

import jodd.props.Props;
import net.mayee.alice.common.Definiens;
import net.mayee.alice.entity.admin.account.Language;
import net.mayee.alice.entity.admin.account.User;
import net.mayee.alice.filter.ShiroAdminDbRealm;
import net.mayee.alice.functions.base.BaseFunctions;
import net.mayee.alice.web.controller.base.BaseController;
import net.mayee.common.AliceHelper;
import net.mayee.common.Uploader;
import net.mayee.common.utils.Encodes;
import net.mayee.leo.LeoEncrypt;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.apache.shiro.subject.Subject;
import org.json.JSONException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Controller
public class MyProfileController extends BaseController {

    @RequiresUser
    @RequestMapping(value = "/sdm/prof/me")
    public String myProfile(Model model) {
        Subject currentUser = SecurityUtils.getSubject();
        ShiroAdminDbRealm.ShiroUser shiroUser = (ShiroAdminDbRealm.ShiroUser) currentUser.getPrincipal();
        User user = this.getUserService().getByLoginName(shiroUser.getLoginName());

        model.addAttribute("user", user);
        return "profile/me/overview";
    }

    @RequiresUser
    @RequestMapping(value = "/prof/help")
    public String help(Model model) {
        Subject currentUser = SecurityUtils.getSubject();
        ShiroAdminDbRealm.ShiroUser shiroUser = (ShiroAdminDbRealm.ShiroUser) currentUser.getPrincipal();
        User user = this.getUserService().getByLoginName(shiroUser.getLoginName());

        model.addAttribute("user", user);
        return "profile/me/help";
    }

    @RequiresUser
    @RequestMapping(value = "/prof/accS")
    public String accountSetting(Model model) {
        Props props = AliceHelper.getInstance().getJoddProps();

        Subject currentUser = SecurityUtils.getSubject();
        ShiroAdminDbRealm.ShiroUser shiroUser = (ShiroAdminDbRealm.ShiroUser) currentUser.getPrincipal();
        User user = this.getUserService().getByLoginName(shiroUser.getLoginName());

        List<Language> lagList = this.getLanguageService().getAll();
        model.addAttribute("lagList", lagList);

        model.addAttribute("user", user);
        model.addAttribute("rsa_modulus", props.getValue("encrypt.rsa.modulus"));
        model.addAttribute("rsa_exponent", props.getValue("encrypt.rsa.public.exponent"));
        return "profile/me/accountSetting";
    }

    @RequiresUser
    @RequestMapping(value = "/prof/accS/ajax/U", method = RequestMethod.POST)
    public void accountSettingUAjax(@ModelAttribute("user") User user,
                                    HttpServletResponse response, HttpServletRequest request,
                                    Model model) throws IOException, JSONException {
        List<String> errorMsgList = validator(user);

        /* 取出当前用户 */
        Subject currentUser = SecurityUtils.getSubject();
        ShiroAdminDbRealm.ShiroUser shiroUser = (ShiroAdminDbRealm.ShiroUser) currentUser.getPrincipal();
        User cUser = this.getUserService().getByLoginName(shiroUser.getLoginName());
        if (cUser != null) {
            cUser.setName(user.getName());
            cUser.setPhone(user.getPhone());
            cUser.setEmail(user.getEmail());
            int lagId = user.getLanguage().getId();
            cUser.getLanguage().setId(lagId);
            this.getUserService().updateUser(cUser, null);

            //change language
            Language lag = this.getLanguageService().getLanguage(lagId);
            this.setSessionLocale(lag.getCode());

            shiroUser.setLagCode(lag.getCode());
        } else {
            errorMsgList.add(this.getMessage("net.mayee.alice.msg.sys.user.user_does_not_exist", "用户不存在！"));
        }

        request.setAttribute("reJSON",
                this.getAjaxUpdateJSONString(errorMsgList,
                        this.getMessage("net.mayee.alice.global.save_success", "保存成功！")));
    }

    @RequiresUser
    @RequestMapping(value = "/prof/accS/ajax2/PUL", method = RequestMethod.POST)
    public void accountSettingPhotoUploadAjax(HttpServletResponse response, HttpServletRequest request,
                                              Model model) throws Exception {
        HashMap<String, String> msgMap = new HashMap<String, String>();
        List<String> errorMsgList = new ArrayList<String>();
        request.setCharacterEncoding(Uploader.DEFAULT_CHARSET);
        response.setCharacterEncoding(Uploader.DEFAULT_CHARSET);

        Uploader up = new Uploader(request, Uploader.UPLOAD_TYPE_IMAGE);
        up.upload();
        if ("SUCCESS".equals(up.getState())) {
            File picture = new File(this.getRealPath(getRequest()) + up.getUrl());
            BufferedImage sourceImg = ImageIO.read(new FileInputStream(picture));
            if (sourceImg.getWidth() <= 200 && sourceImg.getHeight() <= 200) {
                /* update self photo */
                Subject currentUser = SecurityUtils.getSubject();
                ShiroAdminDbRealm.ShiroUser shiroUser = (ShiroAdminDbRealm.ShiroUser) currentUser.getPrincipal();
                String uid = shiroUser.getUuid();
                User user = this.getUserService().getUser(uid);
                if (user != null) {
                    User u = new User();
                    u.setUuid(user.getUuid());
                    u.setPhotoImg(up.getUrl());
                    this.getUserService().updateUser(u, null);

                    /* 更新缓存中的顶部小头像 */
                    shiroUser.setPhoto(up.getUrl());

                    msgMap.put(Definiens.MSG_DESC, this.getMessage("net.mayee.alice.global.save_success", "保存成功！"));
                    msgMap.put("url", BaseFunctions.getPath() + "/" + up.getUrl());
                } else {
                    errorMsgList.add(this.getMessage("net.mayee.alice.msg.sys.user.user_does_not_exist", "用户不存在！"));
                }
            } else {
                errorMsgList.add(this.getMessage("net.mayee.alice.msg.profile.me.image_size_error", "图片尺寸不能大于 200＊200 像素！"));
            }
        } else {
            errorMsgList.add(up.getState());
        }

        response.getWriter().write(this.getAjaxUpdateJSONString(errorMsgList, msgMap));
    }

    @RequiresUser
    @RequestMapping(value = "/prof/accS/ajax/RPW", method = RequestMethod.POST)
    public void resetPasswordAjax(HttpServletResponse response, HttpServletRequest request,
                                  Model model) throws IOException, JSONException {
        List<String> errorMsgList = new ArrayList<String>();

        String en_pw1 = request.getParameter("resetPassword1");
        String en_pw2 = request.getParameter("resetPassword2");
        String en_old_pw = request.getParameter("oldPassword");
        String uid = request.getParameter("uid");

        /* decrypt password */
        Props props = AliceHelper.getInstance().getJoddProps();
        String privateExponent = props.getValue("encrypt.rsa.private.exponent");
        String modulus = props.getValue("encrypt.rsa.modulus");

        byte[] de_password1 = null;
        byte[] de_password2 = null;
        byte[] de_old_pw = null;
        try {
            de_password1 = LeoEncrypt.easyDecryptRSAByProviderPirvateKey(
                    modulus,
                    privateExponent,
                    new org.bouncycastle.jce.provider.BouncyCastleProvider(),
                    new BigInteger(en_pw1, 16).toByteArray()
            );
            de_password2 = LeoEncrypt.easyDecryptRSAByProviderPirvateKey(
                    modulus,
                    privateExponent,
                    new org.bouncycastle.jce.provider.BouncyCastleProvider(),
                    new BigInteger(en_pw2, 16).toByteArray()
            );
            de_old_pw = LeoEncrypt.easyDecryptRSAByProviderPirvateKey(
                    modulus,
                    privateExponent,
                    new org.bouncycastle.jce.provider.BouncyCastleProvider(),
                    new BigInteger(en_old_pw, 16).toByteArray()
            );
        } catch (Exception e) {
            e.printStackTrace();
        }

        String pw1 = StringUtils.reverse(new String(de_password1));
        String pw2 = StringUtils.reverse(new String(de_password2));
        String old_pw = StringUtils.reverse(new String(de_old_pw));

        User user = this.getUserService().getUser(uid);
        if(user != null){
            byte[] hashPassword = LeoEncrypt.sha1(old_pw.getBytes(),
                    Encodes.decodeHex(user.getSalt()), Integer.parseInt(props.getValue("encrypt.hash.interations")));

            if(user.getLoginPassword().equals(Encodes.encodeHex(hashPassword))){
                if (LOGIN_PASSWORD_PATTERN.matcher(pw1).matches()) {
                    if (pw1.equals(pw2)) {
                        User u = new User();
                        u.setUuid(user.getUuid());
                        u.setPlainPassword(pw1);
                        this.getUserService().resetPassword(u);
                    } else {
                        errorMsgList.add(
                                this.getMessage("net.mayee.alice.msg.sys.user.pwdif",
                                        new String[]{this.getMessage("net.mayee.alice.web.sys.user.confirm_password")},
                                        "[ 确认密码 ] 两次输入不一致；"));
                    }
                } else {
                    errorMsgList.add(
                            this.getMessage("net.mayee.alice.msg.sys.user.pw_error",
                                    new String[]{this.getMessage("net.mayee.alice.web.sys.user.password")},
                                    "[ 密码 ] 只能包含大小写字母、数字和下划线，长度4 ~ 16个字符；"));
                }
            }else{
                errorMsgList.add(
                        this.getMessage("net.mayee.alice.msg.sys.user.old_pw_error", "旧密码不正确！"));
            }
        }else{
            errorMsgList.add(
                    this.getMessage("net.mayee.alice.msg.sys.user.user_does_not_exist", "用户不存在！"));
        }

        request.setAttribute("reJSON",
                this.getAjaxRegisterJSONString(errorMsgList,
                        this.getMessage("net.mayee.alice.msg.sys.user.reset_password_success", "密码重置成功！")));
    }

    private List<String> validator(User user) {
        List<String> errorMsgList = new ArrayList<String>();

        if (!EMAIL_PATTERN.matcher(user.getEmail().trim()).matches()) {
            errorMsgList.add(this.getMessage("net.mayee.alice.msg.sys.user.email_error",
                    new String[]{this.getMessage("net.mayee.alice.web.sys.user.email")},
                    "[ 电子邮箱 ] 请输入合法的邮箱地址；"));
        }

        String name = user.getName().trim();
        if (name.length() < 2 || name.length() > 10) {
            errorMsgList.add(this.getMessage("net.mayee.alice.msg.sys.user.name_error",
                    new String[]{this.getMessage("net.mayee.alice.web.sys.user.name")},
                    "[ 姓名 ] 长度在2 ~ 10个字符之间；"));
        }

        return errorMsgList;
    }

}
